package com.smart.community.work.controller;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.DateUtils;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.property.service.DataScopeFeign;
import com.smart.community.work.dto.CleaningAreaDTO;
import com.smart.community.work.dto.CleaningAreaQueryDTO;
import com.smart.community.work.dto.CleaningRecordQueryDTO;
import com.smart.community.work.dto.CleaningTaskQueryDTO;
import com.smart.community.work.dto.CleaningTaskStartDTO;
import com.smart.community.work.dto.CleaningTaskCompleteDTO;
import com.smart.community.work.entity.CleaningArea;
import com.smart.community.work.entity.CleaningRecord;
import com.smart.community.work.entity.CleaningTask;
import com.smart.community.work.service.CleaningService;
import com.smart.community.work.vo.CleaningAreaVO;
import com.smart.community.work.vo.CleaningRecordVO;
import com.smart.community.work.vo.CleaningTaskVO;
import com.smart.community.work.vo.CleaningTaskDetailVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 保洁管理控制器
 * 
 * 严格按照《Java后端SpringBoot代码开发规范_重构版.md》Controller规范实现：
 * - 统一返回格式：使用Result统一包装返回结果
 * - 参数验证：使用@Valid注解进行参数验证
 * - 异常处理：使用统一的异常处理机制，异常往外抛
 * - 完整注释：所有接口都有完整的Swagger文档注释
 * - 权限控制：使用SecurityUtils获取当前用户信息
 * - 日志记录：记录关键操作日志，避免Controller层log.error
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/work/cleaning")
@RequiredArgsConstructor
@Validated
@Tag(name = "保洁管理", description = "保洁管理相关接口")
public class CleaningController {
	private final DataScopeFeign dataScopeFeign;
    private final CleaningService cleaningService;

    // ========================= 保洁区域管理 =========================
    
    @GetMapping("/area/list")
    @Operation(summary = "分页查询保洁区域", description = "分页查询保洁区域列表")
    public Result<IPage<CleaningAreaVO>> getAreaPage(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "区域名称") @RequestParam(required = false) String areaName,
            @Parameter(description = "区域类型") @RequestParam(required = false) String areaType,
            @Parameter(description = "社区ID") @RequestParam(required = false) Long communityId,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "物业公司ID列表") @RequestParam(required = false) List<Long> propertyCompanyIds) throws Exception {
        log.info("分页查询保洁区域，页码：{}，每页大小：{}，区域名称：{}，区域类型：{}，社区ID：{}，状态：{}，物业公司ID列表：{}", 
                pageNum, pageSize, areaName, areaType, communityId, status, propertyCompanyIds);
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        // 创建DTO对象
        CleaningAreaQueryDTO queryDTO = new CleaningAreaQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setAreaName(areaName);
        queryDTO.setAreaType(areaType);
        queryDTO.setCommunityId(communityId);
        queryDTO.setStatus(status);
        queryDTO.setPropertyCompanyIds(propertyCompanyIds);
        
        IPage<CleaningAreaVO> result = cleaningService.selectCleaningAreaPage(queryDTO);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "创建保洁区域",
        logType = 2,
        moduleName = "保洁管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/area")
    @Operation(summary = "创建保洁区域", description = "创建新的保洁区域")
    public Result<Long> createArea(@Valid @RequestBody CleaningAreaDTO areaDTO) throws Exception {
        log.info("创建保洁区域，参数：{}", areaDTO);
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        // 设置创建人
        areaDTO.setCreateBy(currentUserId);
        
        Long areaId = cleaningService.createCleaningArea(areaDTO);
        return Result.success("创建保洁区域成功", areaId);
    }

    @GetMapping("/area/{id}")
    @Operation(summary = "获取保洁区域详情", description = "根据ID获取保洁区域详情")
    public Result<CleaningAreaVO> getAreaById(
            @Parameter(description = "区域ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("获取保洁区域详情，ID：{}", id);
        CleaningAreaVO result = cleaningService.selectCleaningAreaById(id);
        return Result.success(result);
    }


    @ApiLog(
        logTitle = "更新保洁区域",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/area")
    @Operation(summary = "更新保洁区域", description = "更新保洁区域信息")
    public Result<Boolean> updateArea(@Valid @RequestBody CleaningArea cleaningArea) throws Exception {
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        Boolean result = cleaningService.updateCleaningArea(cleaningArea);
        return Result.success("保洁区域更新成功", result);
    }

    @ApiLog(
        logTitle = "删除保洁区域",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/area/{id}")
    @Operation(summary = "删除保洁区域", description = "根据ID删除保洁区域")
    public Result<Boolean> deleteArea(
            @Parameter(description = "区域ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("删除保洁区域，ID：{}", id);
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        Boolean result = cleaningService.deleteCleaningArea(id, currentUserId);
        return Result.success("保洁区域删除成功", result);
    }

    // ========================= 保洁任务管理 =========================

    @GetMapping("/task/user/{userId}")
    @Operation(summary = "查询用户保洁任务", description = "根据用户ID查询保洁任务列表")
    public Result<List<CleaningTaskVO>> getTaskByUserId(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotNull Long userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        log.info("查询用户保洁任务，用户ID：{}，开始日期：{}，结束日期：{}", userId, startDate, endDate);
        
        // 日期参数解析
        LocalDate startDateParsed = null;
        if (startDate != null && !startDate.trim().isEmpty()) {
            try {
                startDateParsed = DateUtils.parseDate(startDate);
                if (startDateParsed == null) {
                    return Result.fail("开始日期格式不正确，请使用 yyyy-MM-dd 格式");
                }
            } catch (Exception e) {
                return Result.fail("开始日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        LocalDate endDateParsed = null;
        if (endDate != null && !endDate.trim().isEmpty()) {
            try {
                endDateParsed = DateUtils.parseDate(endDate);
                if (endDateParsed == null) {
                    return Result.fail("结束日期格式不正确，请使用 yyyy-MM-dd 格式");
                }
            } catch (Exception e) {
                return Result.fail("结束日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        // 日期范围验证
        if (startDateParsed != null && endDateParsed != null && startDateParsed.isAfter(endDateParsed)) {
            return Result.fail("开始日期不能晚于结束日期");
        }
        
        List<CleaningTaskVO> result = cleaningService.selectCleaningTaskByUserId(userId, startDateParsed, endDateParsed);
        return Result.success(result);
    }

    @GetMapping("/task/list")
    @Operation(summary = "分页查询保洁任务", description = "分页查询保洁任务列表")
    public Result<IPage<CleaningTaskVO>> getTaskPage(@Valid @ModelAttribute CleaningTaskQueryDTO queryDTO) throws Exception {
        log.info("分页查询保洁任务，查询参数：{}", queryDTO);
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        DataScopeInfo userDataScope = dataScopeFeign.getUserDataScope(currentUserId);
        // 获取当前用户角色列表
        List<String> userRoles = SecurityUtils.getRoleList();
        log.info("当前用户角色列表：{}", userRoles);
        
        // 判断是否为管理员角色（物业管理员或保洁管理）
        boolean isPropertyAdmin = userDataScope.isPropertyAdmin();
        boolean isCleaningAdmin = userDataScope.isCleaningAdmin();
        boolean isSuperAdmin = userDataScope.isSuperAdmin();
        
        // 如果不是管理员角色，则只能查看分配给自己的任务
        if (!isPropertyAdmin && !isCleaningAdmin && !isSuperAdmin) {
            log.info("用户非管理员角色，限制查询范围：只查看分配给用户ID={}的任务", currentUserId);
            queryDTO.setAssignedUserId(currentUserId);
        } else {
            log.info("用户为管理员角色，可查看所有任务");
        }
        
        IPage<CleaningTaskVO> result = cleaningService.selectCleaningTaskPage(queryDTO);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "创建保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/task")
    @Operation(summary = "创建保洁任务", description = "创建新的保洁任务")
    public Result<Boolean> createTask(@Valid @RequestBody CleaningTask cleaningTask) throws Exception {
        log.info("创建保洁任务，任务名称：{}", cleaningTask.getTaskName());
        Boolean result = cleaningService.createCleaningTask(cleaningTask);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "更新保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/task")
    @Operation(summary = "更新保洁任务", description = "更新保洁任务信息")
    public Result<Boolean> updateTask(@Valid @RequestBody CleaningTask cleaningTask) throws Exception {
        Boolean result = cleaningService.updateCleaningTask(cleaningTask);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "分配保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/task/{taskId}/assign")
    @Operation(summary = "分配保洁任务", description = "分配保洁任务给指定用户")
    public Result<Boolean> assignTask(
            @Parameter(description = "任务ID", required = true) @PathVariable @NotNull Long taskId,
            @Parameter(description = "用户ID", required = true) @RequestParam @NotNull Long userId) throws Exception {
        log.info("分配保洁任务，任务ID：{}，用户ID：{}", taskId, userId);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.assignCleaningTask(taskId, userId, currentUserId);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "删除保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/task/{id}")
    @Operation(summary = "删除保洁任务", description = "根据ID删除保洁任务")
    public Result<Boolean> deleteTask(
            @Parameter(description = "任务ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("删除保洁任务，ID：{}", id);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.deleteCleaningTask(id, currentUserId);
        return Result.success(result);
    }

    @GetMapping("/task/{id}")
    @Operation(summary = "获取保洁任务详情", description = "根据ID获取保洁任务详情")
    public Result<CleaningTaskVO> getTaskDetail(
            @Parameter(description = "任务ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("获取保洁任务详情，任务ID：{}", id);
        CleaningTaskVO result = cleaningService.getCleaningTaskDetail(id);
        return Result.success(result);
    }

    @GetMapping("/task/{id}/detail")
    @Operation(summary = "获取保洁任务详细信息", description = "根据ID获取保洁任务详细信息，包含执行记录")
    public Result<CleaningTaskDetailVO> getTaskDetailInfo(
            @Parameter(description = "任务ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("获取保洁任务详细信息，任务ID：{}", id);
        CleaningTaskDetailVO result = cleaningService.getCleaningTaskDetailInfo(id);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "开始执行保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PostMapping("/task/start")
    @Operation(summary = "开始执行保洁任务", description = "保洁人员开始执行任务")
    public Result<Boolean> startTask(@Valid @RequestBody CleaningTaskStartDTO startDTO) throws Exception {
        log.info("开始执行保洁任务，任务ID：{}", startDTO.getTaskId());
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.startCleaningTask(startDTO, currentUserId);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "完成保洁任务",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PostMapping("/task/complete")
    @Operation(summary = "完成保洁任务", description = "保洁人员完成任务并提交记录")
    public Result<Boolean> completeTask(@Valid @RequestBody CleaningTaskCompleteDTO completeDTO) throws Exception {
        log.info("完成保洁任务，任务ID：{}", completeDTO.getTaskId());
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.completeCleaningTask(completeDTO, currentUserId);
        return Result.success(result);
    }

    // ========================= 保洁记录管理 =========================

    @GetMapping("/record/user/{userId}")
    @Operation(summary = "查询用户保洁记录", description = "根据用户ID查询保洁记录列表")
    public Result<List<CleaningRecordVO>> getRecordByUserId(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotNull Long userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) LocalDate endDate) throws Exception {
        log.info("查询用户保洁记录，用户ID：{}，开始日期：{}，结束日期：{}", userId, startDate, endDate);
        List<CleaningRecordVO> result = cleaningService.selectCleaningRecordByUserId(userId, startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/record/list")
    @Operation(summary = "分页查询保洁记录", description = "分页查询保洁记录列表，支持基于角色的权限控制")
    public Result<IPage<CleaningRecordVO>> getRecordPage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "任务ID") @RequestParam(required = false) Long taskId,
            @Parameter(description = "用户ID") @RequestParam(required = false) Long userId,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            log.warn("用户未登录，无法查询保洁记录");
            return Result.fail("用户未登录");
        }
        // 构建查询参数DTO
        CleaningRecordQueryDTO queryDTO = new CleaningRecordQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setTaskId(taskId);
        queryDTO.setUserId(userId);
        queryDTO.setStatus(status);
        
        // 日期参数解析
        if (startDate != null && !startDate.trim().isEmpty()) {
            try {
                queryDTO.setStartDate(LocalDate.parse(startDate));
            } catch (Exception e) {
                log.error("解析开始日期失败: {}", startDate, e);
                return Result.fail("开始日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        if (endDate != null && !endDate.trim().isEmpty()) {
            try {
                queryDTO.setEndDate(LocalDate.parse(endDate));
            } catch (Exception e) {
                log.error("解析结束日期失败: {}", endDate, e);
                return Result.fail("结束日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        // 调用Service层进行权限控制和数据查询
        IPage<CleaningRecordVO> result = cleaningService.selectCleaningRecordPageWithPermission(queryDTO, currentUserId);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "提交保洁记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/record")
    @Operation(summary = "提交保洁记录", description = "提交保洁工作记录")
    public Result<Boolean> submitRecord(@Valid @RequestBody CleaningRecord cleaningRecord) throws Exception {
        log.info("提交保洁记录，任务ID：{}", cleaningRecord.getTaskId());
        Boolean result = cleaningService.submitCleaningRecord(cleaningRecord);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "验收保洁记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/record/{recordId}/approve")
    @Operation(summary = "验收保洁记录", description = "验收保洁工作记录")
    public Result<Boolean> approveRecord(
            @Parameter(description = "记录ID", required = true) @PathVariable @NotNull Long recordId,
            @Parameter(description = "评分", required = true) @RequestParam @NotNull Integer score,
            @Parameter(description = "验收备注") @RequestParam(required = false) String remark) throws Exception {
        log.info("验收保洁记录，记录ID：{}，评分：{}", recordId, score);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.approveCleaningRecord(recordId, score, remark, currentUserId);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "更新保洁记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/record")
    @Operation(summary = "更新保洁记录", description = "更新保洁记录信息")
    public Result<Boolean> updateRecord(@Valid @RequestBody CleaningRecord cleaningRecord) throws Exception {
        Boolean result = cleaningService.updateCleaningRecord(cleaningRecord);
        return Result.success(result);
    }

    @ApiLog(
        logTitle = "删除保洁记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/record/{id}")
    @Operation(summary = "删除保洁记录", description = "根据ID删除保洁记录")
    public Result<Boolean> deleteRecord(
            @Parameter(description = "记录ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("删除保洁记录，ID：{}", id);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = cleaningService.deleteCleaningRecord(id, currentUserId);
        return Result.success(result);
    }

    // ========================= 统计查询 =========================

    @GetMapping("/statistics/user/{userId}")
    @Operation(summary = "获取用户保洁统计", description = "获取指定用户的保洁工作统计信息")
    public Result<Map<String, Object>> getUserStatistics(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotNull Long userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) LocalDate endDate) throws Exception {
        log.info("获取用户保洁统计，用户ID：{}，开始日期：{}，结束日期：{}", userId, startDate, endDate);
        Map<String, Object> result = cleaningService.getUserCleaningStatistics(userId, startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取保洁统计信息", description = "获取保洁工作统计信息")
    public Result<Map<String, Object>> getStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) LocalDate endDate) throws Exception {
        log.info("获取保洁统计信息，开始日期：{}，结束日期：{}", startDate, endDate);
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Map<String, Object> result = cleaningService.getCleaningStatistics(currentUserId, startDate, endDate);
        return Result.success(result);
    }
}